package cn.tedu._03vehicle.base.exception;

import cn.tedu._03vehicle.base.response.JsonResult;
import cn.tedu._03vehicle.base.response.StatusCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * SpringMVC中专门处理异常的机制
 * 1。标识该类为全局异常处理器
 * 2.当控制器抛出异常后，框架会先检查有没有定义全局异常处理器；
 *  2.1未定义：默认的异常处理机制直接抛出异常
 *  2.2定义了：检查有没有定义对应的异常处理方法
 */
//@ControllerAdvice
@Slf4j
@RestControllerAdvice   //组合注解  等价于@ResponseBody+@ControllerAdvice
public class GlobalExceptionHandler {
    /**
     * ExceptionHandler注解修饰的方法，表示处理异常的方法
     * 1.添加在方法上，标识该方法为异常处理方法
     * @return
     */
    @ExceptionHandler
//    @ResponseBody
    public JsonResult doHandlerIllegalArgumentException(IllegalArgumentException ex){
        String data = ex.getMessage();
        log.error("doHandlerIllegalArgumentException"+data);
        return new JsonResult(StatusCode.OPERATION_FAILED,data);
    }
/**
 * 所有异常都能处理的异常处理器方法------一般是最后加
 */
    //Throwable所有异常都能被它接收，处理所有异常方法
//    @ExceptionHandler
//    public JsonResult doHandleThrowable(Throwable ex){
//        String data = ex.getMessage();
//        log.error("doHandleThrowable"+data);
//        return new JsonResult(StatusCode.THROWABLE_ERROR,data);
//    }

    /**
     * 第二个异常处理方法
     * @param ex
     * @return
     */
    @ExceptionHandler
    public JsonResult doHandleMethodArgumentNotValidException(MethodArgumentNotValidException ex){
//        String data = ex.getMessage();
        String data = ex.getFieldError().getDefaultMessage();      //只有这样写才能获得message消息
        log.error("doHandle"+data);
        return new JsonResult(StatusCode.VALIDATION_ERROR,data);
    }

    /**
     * 第4个异常处理方法,可以接受父类异常,任何抛出运行时异常都能处理
     * @param ex
     * @return
     */
        //可以接收子类的异常，子类找不到就找父类
    @ExceptionHandler
    public JsonResult doHandleRuntimeException(RuntimeException er){
        String data = er.getMessage();
        log.error("doHandleRuntimeException"+data);
        return new JsonResult(StatusCode.OPERATION_FAILED,data);
    }

    /**
     *
     * @param ex
     * @return
     */
    @ExceptionHandler
    public JsonResult doHandleConstraintViolationException(ConstraintViolationException ex){

//        List<String> errors = ex.getConstraintViolations().stream()
//                .map(violation -> violation.getMessage())
//                .collect(Collectors.toList());
//        String data = String.join(", ", errors);
//        log.error("doHandleConstraintViolationException: {}", data);
//        return new JsonResult(StatusCode.VALIDATION_ERROR, data);
        String data = ex.getMessage().split(":")[1].trim();
        System.out.println(data);
        log.error("doHandleConstraintViolationException"+data);

        return new JsonResult(StatusCode.VALIDATION_ERROR,data);
    }
}
